package testalgorithm;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.util.Scanner;
/**
 *
 * @author haoliang.donghl
 */
public abstract class AbstractAlgorithm {
    public static String DICTIONARY_NAME = "3";
    public static int NUM_APP = 400;
    public static int NUM_MACHINE = 5;
    public static float CPU_UP_BOUND = 0.6f;

    public static final int COST_F5 = 5;
    public static final int COST_SIZE = 1;
    public static final float CPU_LOW_BOUND = 0.0f;
    public static final float PER_CPU_BOUND = 0.2f;
    public static int[][] matrixIn, matrixOut;
    public static int[][] matrixCost;
    public static int[] vectorAppSize;
    public static float[] vectorAppCPU;
    public static float[] vectorMachineCPU;
    public static float[][] matrixState;

    protected static void calculateMatrixCost(int[][] matrix) {
        for (int i = 0; i < NUM_APP; i++) {
            for (int j = 0; j < NUM_MACHINE; j++) {
                if (matrix[i][j] == 0) {
                    matrixCost[i][j] = COST_SIZE * vectorAppSize[i] + COST_F5;
                } else if (matrix[i][j] == 1) {
                    matrixCost[i][j] = COST_F5;
                } else {
                    matrixCost[i][j] = 0;
                }
            }
        }
    }

    protected static void readMatrixInOut(int[][] matrix, String file) {
        String s;
        try {
            Scanner scanner = new Scanner(new File(file));
            for (int i = 0; i < NUM_APP; i++) {
                s = scanner.nextLine();
                for (int j = 0; j < NUM_MACHINE; j++) {
                    matrix[i][j] = s.charAt(j) - '0';
                }
            }
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected static void readVectorCPU(String file) {
        try {
            Scanner scanner = new Scanner(new File(file));
            for (int i = 0; i < NUM_APP; i++) {
                vectorAppCPU[i] = scanner.nextFloat();
            }
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected static void readVectorSize(String file) {
        try {
            Scanner scanner = new Scanner(new File(file));
            for (int i = 0; i < NUM_APP; i++) {
                vectorAppSize[i] = scanner.nextInt();
            }
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected static void printAppNeeds(){
        float sum = 0;
        for (int i = 0; i < NUM_APP; i++){
            sum += vectorAppCPU[i];
        }
        /*
        System.out.print("ALL: ");
        System.out.println(sum);
        */
    }

    protected static int checkConstraint(int[][] matrix) {
        int runningNum;
        float perCPU;
        for (int i = 0; i < NUM_APP; i++) {
            runningNum = 0;
            for (int j = 0; j < NUM_MACHINE; j++) {
                if (matrix[i][j] == 2) {
                    runningNum++;
                }
            }

            if (runningNum == 0) {
                perCPU = 0;
            } else {
                perCPU = ((float) vectorAppCPU[i]) / runningNum;
            }

            for (int j = 0; j < NUM_MACHINE; j++) {
                if (matrix[i][j] == 2) {
                    matrixState[i][j] = perCPU;
                } else {
                    matrixState[i][j] = 0;
                }
            }
        }

        for (int j = 0; j < NUM_MACHINE; j++) {
            vectorMachineCPU[j] = 0;
            for (int i = 0; i < NUM_APP; i++) {
                vectorMachineCPU[j] += matrixState[i][j];
            }
        }

        for (int j = 0; j < NUM_MACHINE; j++){
            if (vectorMachineCPU[j] > CPU_UP_BOUND ||
                    vectorMachineCPU[j] < CPU_LOW_BOUND) {
                return j;
            }
        }

        return -1;
    }

    protected static int calculateCost() {
        int cost = 0;
        for (int i = 0; i < NUM_APP; i++) {
            for (int j = 0; j < NUM_MACHINE; j++) {
                if (matrixOut[i][j] == 2) {
                    cost += matrixCost[i][j];
                }
            }
        }
        return cost;
    }

    protected static void readParameter(String file){
        try {
            Scanner scanner = new Scanner(new File(file));
            NUM_APP = scanner.nextInt();
            NUM_MACHINE = scanner.nextInt();
            CPU_UP_BOUND = scanner.nextFloat();
            scanner.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    protected static void readFromFile(String dictionary){
        readMatrixInOut(matrixIn, dictionary + "\\in.txt");
        readVectorSize(dictionary + "\\size.txt");
        readVectorCPU(dictionary + "\\cpu.txt");
    }

    protected static void printMachineCPU(){
        /*
        for (int i = 0; i < NUM_MACHINE; i++){
            System.out.print("MACHINE");
            System.out.print("");
            System.out.print(i + 1);
            System.out.print(": ");
            System.out.println(vectorMachineCPU[i]);
        }
        */
    }

    protected static void copyArray(int[][] dest, int[][] src){
        for (int i = 0; i < NUM_APP; i++){
            for (int j = 0; j < NUM_MACHINE; j++){
                dest[i][j] = src[i][j];
            }
        }
    }

    protected static void printMatrixInOut(int[][] matrix, String filename) {
        createFile(filename);
        try {
            PrintWriter out = new PrintWriter(
                    new BufferedWriter(new FileWriter(filename)));
            for (int i = 0; i < NUM_APP; i++) {
                for (int j = 0; j < NUM_MACHINE; j++) {
                    out.print(matrix[i][j]);
                }
                out.println();
            }
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void createFile(String filename) {
        try {
            File file = new File(filename);
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
